package com.example.myapplication.algorithm;

public class HeartRateCalibrator {
    // 正常心率范围 (单位: 次/分钟)
    private static final int DEFAULT_MIN_HEART_RATE = 50;
    private static final int DEFAULT_MAX_HEART_RATE = 210;
    // 默认最大允许变化值
    private static final int DEFAULT_MAX_ALLOWED_CHANGE = 3;
    // 当连续三次超过变化阈值时使用的放宽值
    private static final int RELAXED_MAX_ALLOWED_CHANGE = 12;
    // 平滑窗口大小
    private static final int SMOOTHING_WINDOW_SIZE = 3;
    // 心率历史记录
    private final int[] heartRateHistory = new int[SMOOTHING_WINDOW_SIZE];
    private int historyIndex = 0;
    private int historyCount = 0;
    // 连续超过阈值的计数器
    private int consecutiveOverThreshold = 0;
    // 当前使用的最大允许变化值
    private int currentMaxAllowedChange = DEFAULT_MAX_ALLOWED_CHANGE;

    /**
     * 使用默认参数创建心率校准器
     */
    private static HeartRateCalibrator INSTANCE;
    public synchronized static HeartRateCalibrator getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new HeartRateCalibrator();
        }
        return INSTANCE;
    }
    /**
     * 校准心率
     * @param rawHeartRate 原始心率值
     * @return 校准后的心率值
     */
    public synchronized int calibrate(int rawHeartRate) {
        // 第一步：限制在生理范围内
        int clamped = Math.max(DEFAULT_MIN_HEART_RATE, Math.min(DEFAULT_MAX_HEART_RATE, rawHeartRate));

        // 如果没有历史数据，直接返回限制后的值
        if (historyCount == 0) {
            addToHistory(clamped);
            return clamped;
        }

        // 获取上一次的心率值
        int lastRate = getLastHeartRate();

        // 检查当前心率变化是否超过阈值
        boolean isOverThreshold = Math.abs(clamped - lastRate) > currentMaxAllowedChange;

        // 更新连续超过阈值的计数器
        if (isOverThreshold) {
            consecutiveOverThreshold++;

            // 如果连续三次超过阈值，放宽限制
            if (consecutiveOverThreshold >= 3) {
                currentMaxAllowedChange = RELAXED_MAX_ALLOWED_CHANGE;
            }
        } else {
            // 重置计数器并恢复默认限制
            consecutiveOverThreshold = 0;
            currentMaxAllowedChange = DEFAULT_MAX_ALLOWED_CHANGE;
        }

        // 第二步：限制突变（使用当前的最大允许变化值）
        int bounded;
        if (isOverThreshold) {
            // 如果变化过大，限制变化幅度
            if (clamped > lastRate) {
                bounded = lastRate + currentMaxAllowedChange;
            } else {
                bounded = lastRate - currentMaxAllowedChange;
            }
            bounded = Math.max(DEFAULT_MIN_HEART_RATE, Math.min(DEFAULT_MAX_HEART_RATE, bounded));
        } else {
            bounded = clamped;
        }

        // 第三步：平滑处理 (移动平均)
        addToHistory(bounded);
        int smoothed = calculateSmoothedValue();

        return smoothed;
    }

    /**
     * 重置校准器，清除历史数据
     */
    public synchronized void reset() {
        historyIndex = 0;
        historyCount = 0;
        consecutiveOverThreshold = 0;
        currentMaxAllowedChange = DEFAULT_MAX_ALLOWED_CHANGE;
    }

    private void addToHistory(int heartRate) {
        heartRateHistory[historyIndex] = heartRate;
        historyIndex = (historyIndex + 1) % SMOOTHING_WINDOW_SIZE;
        if (historyCount < SMOOTHING_WINDOW_SIZE) {
            historyCount++;
        }
    }

    private int getLastHeartRate() {
        if (historyCount == 0) {
            throw new IllegalStateException("没有历史心率数据");
        }
        int lastIndex = (historyIndex - 1 + SMOOTHING_WINDOW_SIZE) % SMOOTHING_WINDOW_SIZE;
        return heartRateHistory[lastIndex];
    }

    private int calculateSmoothedValue() {
        if (historyCount == 0) {
            throw new IllegalStateException("没有历史心率数据");
        }
        int sum = 0;
        for (int i = 0; i < historyCount; i++) {
            sum += heartRateHistory[i];
        }
        return sum / historyCount;
    }

    // 获取当前使用的最大允许变化值（用于调试或监控）
    public synchronized int getCurrentMaxAllowedChange() {
        return currentMaxAllowedChange;
    }
}